﻿using PageAdmin.Utils.ORM;
using PageAdmin.Utils.ORM.PropertyDescriptor;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace PageAdmin.Utils.BLL
{
    /// <summary>
    //相关数据的处理逻辑
    /// </summary>
    public class RelateDataBLL
    {
        private static MethodInfo GetListDataMethod;
        private static MethodInfo GetDataMethod;
        static RelateDataBLL()
        {
            //静态保存，避免每次反射查找
            GetDataMethod = typeof(RelateDataBLL).GetMethod("GetData", BindingFlags.NonPublic | BindingFlags.Static, null, new Type[] { typeof(DataBaseContext), typeof(string), typeof(int), typeof(string), typeof(string) }, null);
            GetListDataMethod = typeof(RelateDataBLL).GetMethod("GetListData", BindingFlags.NonPublic | BindingFlags.Static, null, new Type[] { typeof(DataBaseContext), typeof(string), typeof(IEnumerable<int>), typeof(string), typeof(string) }, null);
        }


        /// <summary>
        /// 设置关联数据的属性值
        /// </summary>
        /// <param name="goodModelId"></param>
        /// <returns></returns>
        public static void SetRelateData<T>(DataBaseContext dbContext, T tModel,bool isDetail = true) where T : class, new()
        {
            DbSet<T> dbSet = dbContext.DbSet<T>();
            IEnumerable<ModelFieldMapped> modelFieldMappedList = dbSet.ModelFieldMappingList.Where(c => c.IsRelateDataMapped == true);
            if (isDetail)
            {
                modelFieldMappedList = modelFieldMappedList.Where(c => c.RelateDataMappedDescriptor.DetailSyncLoad == true);
            }
            else
            {
                modelFieldMappedList = modelFieldMappedList.Where(c => c.RelateDataMappedDescriptor.ListSyncLoad == true);
            }

            foreach (ModelFieldMapped modelFieldMapped in modelFieldMappedList)
            {
                var valueKeyProperty= modelFieldMapped.RelateDataMappedDescriptor.ValueKeyPropertyInfo;
                var relateModelType = modelFieldMapped.RelateDataMappedDescriptor.RelateModelType;
                string relateKey = modelFieldMapped.RelateDataMappedDescriptor.RelateKey; //获取子表外键
                string sqlCondition = modelFieldMapped.RelateDataMappedDescriptor.SqlCondition;
                string orderBy= modelFieldMapped.RelateDataMappedDescriptor.OrderBy;
                if (modelFieldMapped.IsIEnumerable) //一对多
                {
                    IEnumerable<int> valueList = (IEnumerable<int>)valueKeyProperty.GetValue(tModel,null);
                    MethodInfo gerericMethodInfo = GetListDataMethod.MakeGenericMethod(relateModelType);
                    var result = gerericMethodInfo.Invoke(null, new object[] { dbContext, relateKey, valueList, sqlCondition, orderBy });
                    modelFieldMapped.PropertyInfo.SetValue(tModel, result);
                }
                else //一对一
                {
                    int value= (int)valueKeyProperty.GetValue(tModel, null);
                    MethodInfo gerericMethodInfo = GetDataMethod.MakeGenericMethod(relateModelType);
                    var result = gerericMethodInfo.Invoke(null, new object[] { dbContext, relateKey, value, sqlCondition, orderBy });
                    modelFieldMapped.PropertyInfo.SetValue(tModel, result); 
                }

            }
        }

        /// <summary>
        /// 获取一对一的关联数据
        /// </summary>
        /// <typeparam name="RelativeModelType"></typeparam>
        /// <param name="subModel"></param>
        private static RelativeModelType GetData<RelativeModelType>(DataBaseContext dbContext, string relateKey, int value,string sqlCondition=null,string orderBy=null) where RelativeModelType : class, new()
        {
            IGetDetailData<RelativeModelType> detailBLL = new GetDetailDataBLL<RelativeModelType>(dbContext);
            string condition = $"{relateKey}= @relateKey";
            if(!string.IsNullOrEmpty(sqlCondition))
            {
                condition+= " and " + sqlCondition;
            }
            return detailBLL.GetData(condition, orderBy, new { relateKey = value });
        }

        /// <summary>
        /// 获取一对多的关联数据
        /// </summary>
        /// <typeparam name="subModelType"></typeparam>
        /// <param name="subModel"></param>
        private static IEnumerable<subModelType> GetListData<subModelType>(DataBaseContext dbContext, string relateKey, IEnumerable<int> valueList, string sqlCondition = null, string orderBy = null) where subModelType : class, new()
        {
            if(valueList.Count()<=0)
            {
                return new List<subModelType>();
            }
            string condition = $"{relateKey} in {string.Join(",",valueList)}";
            if (!string.IsNullOrEmpty(sqlCondition))
            {
                condition += " and " + sqlCondition;
            }
            IGetListData<subModelType> listBLL = new GetListDataBLL<subModelType>(dbContext);
            listBLL.QueryCondition = condition;
            listBLL.OrderBy = orderBy;
            return listBLL.GetList(null);
        }

    }
}